﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FantastPlatform.Framework.Core;
using NHibernate;
using FantastPlatform.Framework.IService;
using NHibernate.Criterion;
using FantastPlatform.Framework.Common;
namespace FantastPlatform.Framework.Service
{
    /// <summary>
    /// 专为树形结构对象服务的增，删，查
    /// </summary>
    /// <typeparam name="IEntity"></typeparam>
    /// <typeparam name="Entity"></typeparam>
    public abstract class NodeService<IEntity, Entity> : DataService<IEntity,Entity> , INodeService<IEntity>
        where IEntity : class,IItem, INode<IEntity>
        where Entity : class, IEntity, new()
    {
        private void RemoveChildrenEnable(IList<IEntity> list)
        {
            foreach (IEntity entity in list)
            {
                if (!CollectionHelper.IsNullOrEmpty<IEntity>(entity.Children))
                {
                    IList<IEntity> relLists = new List<IEntity>();
                    RemoveChildrenEnable(entity.Children);
                    foreach (IEntity childrenEntity in entity.Children)
                    {
                        if (childrenEntity.Enable == false)
                        {
                            continue;
                        }
                        else
                        {
                            relLists.Add(childrenEntity);
                        }
                    }
                    entity.Children = relLists;
                }
            }
        }
        //树形结构得到子类对象公共方
        public IList<IEntity> GetChildrenByParentId(int Id )
        {
            var list = Get(Id).Children;
            return list;
        }
        public override IList<IEntity> LoadList(IList<Sort> sorts, int pageSize, int page, out int totalCount)
        {
            ICriteria criteria = Session.CreateCriteria(typeof(Entity)).Add(Restrictions.Eq("Level", 1))
                .Add(Expression.Eq("Enable", true));
            ICriteria clone = criteria.Clone() as ICriteria;
            criteria = AddOrderBySorts(criteria, sorts);
            IList<IEntity> list = criteria.SetFirstResult((page - 1) * pageSize).SetMaxResults(pageSize).List<IEntity>();
            totalCount = int.Parse(clone.SetProjection(Projections.RowCount()).UniqueResult().ToString());
           RemoveChildrenEnable(list);
             return list;
        }
        public override object Create(IEntity entity)
        {
            object id = 0;
            ITransaction transaction = null;
            ExecuteTransaction((ITransaction tran)=>
                {
                    if (entity.Parent != null)
                    {
                        IEntity parent = Session.Get<Entity>(entity.Parent.Id);
                        parent.Leaf = false;
                        entity.Level = parent.Level + 1;
                        entity.Leaf = true;
                        DefaultValue(entity);
                        if (!CollectionHelper.IsNullOrEmpty<IEntity>(entity.Children))
                        {
                            entity.Children = entity.Children.Cast<IEntity>().ToList();
                        }
                        Session.Update(parent);
                        id = Session.Save(entity);
                        CreateChildren(entity); 
                    }
                    else
                    {
                        entity.Leaf = true;
                        entity.Level = 1;
                        DefaultValue(entity);
                        if (!CollectionHelper.IsNullOrEmpty<IEntity>(entity.Children))
                        {
                            entity.Children = entity.Children.Cast<IEntity>().ToList();
                        }
                        id = Session.Save(entity);
                        CreateChildren(entity);
                    }
                },transaction);
            return id;
        }
        protected void CreateChildren(IEntity entity)
        {
            ICriteria c = Session.CreateCriteria("User");
            if (!CollectionHelper.IsNullOrEmpty<IEntity>(entity.Children))
            {
                foreach (IEntity e in entity.Children)
                {
                    e.Parent = entity;
                    DefaultValue(e);
                    Create(e);
                }
            }
        }
        //public override void Delete(int id)
        //{
        //    ITransaction transaction = null;
        //    ExecuteTransaction((ITransaction tran) =>
        //        {
        //            IEntity entity = Session.Get<Entity>(id);
        //            if (!Session.Contains(entity))
        //            {
        //                Session.SaveOrUpdate(entity);
        //            }
        //            if (entity.Parent != null)
        //            {
        //                if (entity.Parent.Children.Count == 1)
        //                    entity.Parent.Leaf = true;
        //                Session.Update(entity.Parent);
        //                Session.Delete(entity);
        //            }
        //        }, transaction);
        //}
        private void DeleteChildern(IEntity entity)
        {
            if (entity.Children != null)
            {
                foreach (IEntity childEntity in entity.Children)
                {
                    DeleteChildern(childEntity);
                }
            }
            entity.Enable = false;
            Session.Update(entity);
            if (entity.Parent != null)
            {
                entity.Parent.Leaf = true;
                Session.Update(entity.Parent);
            }
        }
        public void DeleteAndchildren(List<int> ids)
        {
            ITransaction transaction = null;
            ExecuteTransaction((ITransaction tran) =>
                {
                    foreach (int id in ids)
                    {
                        DeleteChildern(Session.Get<Entity>(id));
                    }
                }, transaction);
        }
        public override void Update(IEntity entity)
        {
            ITransaction transaction = null;
            ExecuteTransaction((ITransaction tran) =>
                {
                    //entity = Session.Get<Entity>(entity.Id)
                    entity.Enable = true;
                    IEntity OldEntity = Session.Get<Entity>(entity.Id);
                    IEntity OldParent = OldEntity.Parent;
                    IEntity NewParent=null;
                    if (entity.Parent != null)
                        NewParent = Session.Get<Entity>(entity.Parent.Id);
                    if (OldParent != null && NewParent != null && NewParent.Id != OldParent.Id)
                    {
                        if (NewParent.Level == OldParent.Level)
                        {
                            Session.Update(entity);
                            tran.Commit();
                        }
                        else
                        {
                            entity.Level = NewParent.Level + 1;
                            if (OldEntity.Children != null && OldEntity.Children.Count > 0)
                            {
                                foreach (IEntity c in OldEntity.Children)
                                {
                                    c.Level = NewParent.Level + 2;
                                    Session.Update(c);
                                }
                            }
                            else
                            {
                                entity.Leaf = true;
                            }
                            
                            Session.Evict(OldEntity);
                            Session.Update(entity);

                        }
                    }
                    else if (NewParent == null)
                    {
                        entity.Leaf = true;
                        entity.Level = 1;
                        Session.Evict(OldEntity);
                        Session.Update(entity);


                    }
                    else
                    {
                        Session.Evict(OldEntity);
                        Session.Update(entity);

                    }
                }, transaction);
        }
    }
}
